#include <iostream>
#include <string>
#include <sys/epoll.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "Sock.hpp"

#define NUM 128
#define SIZE 64
// epoll_server.cc 8080
void Usage(std::string proc)
{
    std::cout << "Usage:\n\t" << proc << " port" << std::endl;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    // 创建套接字，等待链接
    uint16_t port = static_cast<uint16_t>(atoi(argv[1]));
    int listen_sock = Sock::Socket();
    Sock::Bind(listen_sock, port);
    Sock::Listen(listen_sock);

    // 创建epoll的句柄
    int epfd = epoll_create(NUM);

    // epoll的事件注册
    struct epoll_event ev;
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = listen_sock;
    epoll_ctl(epfd, EPOLL_CTL_ADD, listen_sock, &ev);

    // 事件循环
    struct epoll_event revs[SIZE];
    while (true)
    {
        // 收集在epoll监控的事件中已经发送的事件
        int timeout = 1000;
        int n = epoll_wait(epfd, revs, SIZE, -1);
        switch (n)
        {
        case -1:
            std::cerr << "epoll error" << std::endl;
            break;
        case 0:
            std::cerr << "epoll timeout..." << std::endl;
            break;
        default:
            std::cout << "事件就绪了" << std::endl;
            for (int i = 0; i < n; ++i)
            {
                // 获取已经准备好的 sock
                int sock = revs[i].data.fd;
                std::cout << "文件描述符: " << sock << " 就绪啦" << std::endl;
                if (revs[i].events & EPOLLIN)
                {
                    std::cout << "文件描述符" << sock << " 上面有事件就绪了" << std::endl;
                    if (sock == listen_sock)
                    {
                        // int newSock = Sock::Accept(sock);
                        // if (newSock >= 0)
                        // {
                        //     std::cout << "获取信新链接成功了" << newSock << std::endl;
                        //     // epoll的事件注册,将new_sock添加到epoll模型当中
                        //     struct epoll_event _ev;
                        //     _ev.events = EPOLLIN;
                        //     _ev.data.fd = newSock;
                        //     epoll_ctl(epfd, EPOLL_CTL_ADD, newSock, &_ev);
                        // }
                        // // 普通读取
                        // else
                        // {
                        //     //do nothing
                        // }
                    }
                    else
                    {
                        // 进行普通读取
                        char buffer[1024];
                        ssize_t s = read(sock, buffer, sizeof(buffer)-1);
                        if(s < 0)
                        {
                            std::cerr << "read failed!" << std::endl;
                            close(sock);
                            epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr);
                            std::cout << "sock: " << sock << "delete from epoll success" << std::endl;
                        }
                        else if(s == 0)
                        {
                            std::cout << "对端关闭了链接" << std::endl;
                            close(sock);
                            epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr);
                            std::cout << "sock: " << sock << "delete from epoll success" << std::endl;
                        }
                        else 
                        {
                            buffer[s] = '\0';
                            std::cout << "client #" << buffer << std::endl;
                        }
                    }
                }
                else if (revs[i].events & EPOLLOUT)
                {
                }
            }
            break;
        }
    }

    close(listen_sock);
    close(epfd);
    return 0;
}